#include "LocLocate.h"

using namespace clang;

SourceLocation rocket::common::getSemiOrRBraceAsEndLoc(SourceLocation end,
                                                       const SourceManager &sm,
                                                       clang::ASTContext &ast) {
  if (end.isMacroID()) {
    if (!Lexer::isAtEndOfMacroExpansion(end, sm, ast.getLangOpts(), &end))
      return end;
  }

  // Break down the source location.
  std::pair<FileID, unsigned> locInfo = sm.getDecomposedLoc(end);

  // Try to load the file buffer.
  bool invalidTemp = false;
  clang::StringRef file = sm.getBufferData(locInfo.first, &invalidTemp);
  if (invalidTemp) return end;

  const char *tokenBegin = file.data() + locInfo.second;

  // Lex from the start of the given location.
  Lexer lexer(sm.getLocForStartOfFile(locInfo.first), ast.getLangOpts(),
              file.begin(), tokenBegin, file.end());
  Token tok;
  lexer.LexFromRawLexer(tok);

  if (tok.is(tok::semi) || tok.is(tok::r_brace) /* || tok.is(tok::r_paren)*/) {
    // if is ";", the end loc is after it
    // NOTE: 当判断“)”为尾时会导致");"类型语句定位错误
    // semi- ; 是尾，用于插入}语法糖
    // r-brace } 也是尾，用于防止已有}的体再插入}时出错（如for的init）

    return tok.getLocation();
    //    return Lexer::getLocForEndOfToken(tok.getLocation(), 0, sm,
    //                                      ast.getLangOpts());
  } else {
    //    if (!IsDecl) return FullSourceLoc();
    // Declaration may be followed with other tokens; such as an __attribute,
    // before ending with a semicolon.
    return getSemiOrRBraceAsEndLoc(
        Lexer::getLocForEndOfToken(tok.getLocation(), 0, sm, ast.getLangOpts()),
        sm, ast);
  }
}
